using Microsoft.Extensions.Caching.Distributed;
using System.Text.Json;
using FServer.Core.Interfaces;

namespace FServer.Infrastructure.Services;

public class RedisCacheService : ICacheService
{
    private readonly IDistributedCache _cache;
    private readonly ILogger<RedisCacheService> _logger;
    private readonly JsonSerializerOptions _jsonOptions;

    public RedisCacheService(IDistributedCache cache, ILogger<RedisCacheService> logger)
    {
        _cache = cache;
        _logger = logger;
        _jsonOptions = new JsonSerializerOptions
        {
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
            WriteIndented = false
        };
    }

    public async Task<T?> GetAsync<T>(string key)
    {
        try
        {
            var value = await _cache.GetStringAsync(key);
            if (string.IsNullOrEmpty(value))
                return default(T);

            return JsonSerializer.Deserialize<T>(value, _jsonOptions);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to get cache key: {Key}", key);
            return default(T);
        }
    }

    public async Task SetAsync<T>(string key, T value, TimeSpan? expiry = null)
    {
        try
        {
            var json = JsonSerializer.Serialize(value, _jsonOptions);
            var options = new DistributedCacheEntryOptions();
            
            if (expiry.HasValue)
            {
                options.SetAbsoluteExpiration(expiry.Value);
            }

            await _cache.SetStringAsync(key, json, options);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to set cache key: {Key}", key);
        }
    }

    public async Task DeleteAsync(string key)
    {
        try
        {
            await _cache.RemoveAsync(key);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to delete cache key: {Key}", key);
        }
    }

    public async Task<bool> ExistsAsync(string key)
    {
        try
        {
            var value = await _cache.GetStringAsync(key);
            return !string.IsNullOrEmpty(value);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to check cache key existence: {Key}", key);
            return false;
        }
    }

    public async Task<Dictionary<string, T>> GetManyAsync<T>(IEnumerable<string> keys)
    {
        var result = new Dictionary<string, T>();
        
        foreach (var key in keys)
        {
            var value = await GetAsync<T>(key);
            if (value != null)
            {
                result[key] = value;
            }
        }
        
        return result;
    }

    public async Task SetManyAsync<T>(Dictionary<string, T> values, TimeSpan? expiry = null)
    {
        var tasks = values.Select(kvp => SetAsync(kvp.Key, kvp.Value, expiry));
        await Task.WhenAll(tasks);
    }

    public async Task DeleteManyAsync(IEnumerable<string> keys)
    {
        var tasks = keys.Select(key => DeleteAsync(key));
        await Task.WhenAll(tasks);
    }

    public async Task<long> IncrementAsync(string key, long value = 1)
    {
        // Redis 分布式缓存不支持原子操作，这里使用简单的实现
        var current = await GetAsync<long>(key) ?? 0;
        var newValue = current + value;
        await SetAsync(key, newValue);
        return newValue;
    }

    public async Task<long> DecrementAsync(string key, long value = 1)
    {
        return await IncrementAsync(key, -value);
    }

    public async Task<bool> SetIfNotExistsAsync<T>(string key, T value, TimeSpan? expiry = null)
    {
        var exists = await ExistsAsync(key);
        if (!exists)
        {
            await SetAsync(key, value, expiry);
            return true;
        }
        return false;
    }

    public async Task<bool> ExpireAsync(string key, TimeSpan expiry)
    {
        // 分布式缓存不支持设置过期时间，这里重新设置值
        var value = await GetAsync<object>(key);
        if (value != null)
        {
            await SetAsync(key, value, expiry);
            return true;
        }
        return false;
    }

    public async Task<TimeSpan?> GetExpiryAsync(string key)
    {
        // 分布式缓存不支持获取过期时间
        return null;
    }

    public async Task<IEnumerable<string>> GetKeysAsync(string pattern)
    {
        // 分布式缓存不支持模式匹配
        return Enumerable.Empty<string>();
    }

    public async Task DeleteByPatternAsync(string pattern)
    {
        // 分布式缓存不支持模式删除
        await Task.CompletedTask;
    }
}
